package tgt

import (
	"bytes"
	_ "embed"
	"fmt"
	log "github.com/sirupsen/logrus"
	"gopkg.in/ini.v1"
	"io"
	"regexp"
	"strconv"
	"vmService/vmservice/ssh"
)

var (
	ansible_dir = "/home/curve/curve/curve-ansible"
	tmp_dir     = "/tmp"
)

//go:embed config/tgt.ini
var iniContent string

//go:embed config/deploy_tgt.yml
var yamlContent string

//tgtIniPath = "./"

func loadTgtIni() *ini.File {
	tgtCfg, err := ini.Load(bytes.NewBufferString(iniContent))
	ini.PrettyFormat = false
	if err != nil {
		log.Fatal("Fail to read tgt ini file: ", err)
		return nil
	}
	return tgtCfg
}

func saveTgtiniToString(iniFile *ini.File) (string, error) {
	ts := ""
	tgtIniBuf := bytes.NewBufferString(ts)
	_, err := iniFile.WriteTo(tgtIniBuf)
	if err != nil {
		return "", err
	}
	return tgtIniBuf.String(), nil
}

func loadTgtYaml() string {
	return yamlContent
	//content, err := os.ReadFile("D:\\Projects\\Go\\virtual-machine-services\\vmservice\\tgt\\deploy_tgt.yml")
	//if err != nil {
	//	log.Fatal("Fail to read tgt yaml file: ", err)
	//	return "", err
	//}
	//return string(content), nil
}

func getSSHInfo() SSHInfo {
	return SSHInfo{
		Network:     "tcp",
		HostAddress: "192.168.0.101:22",
		Username:    "root",
		Password:    "qwAS!@34",
	}
}

func connectSSHClient(info SSHInfo) (*ssh.SSHClient, error) {
	cli := ssh.SSHClient{}
	cli.Init(info.Username, info.Password, info.HostAddress)
	sshClient, err := cli.Connect()
	if err != nil {
		return nil, err
	}
	if err := sshClient.NewSession(); err != nil {
		return nil, err
	}
	// sftp 在远程机器写入配置文件
	if err := sshClient.NewSftpClient(); err != nil {
		return nil, err
	}
	return sshClient, nil
}

func scpConfigFile(client *ssh.SSHClient, iniFileContent, yamlFileContent, iniFilename, yamlFilename string) (int, error) {

	iniSource, err := client.SftpClient.Create(ansible_dir + "/" + iniFilename)
	if err != nil {
		return 5211, fmt.Errorf("failed to open remote file: %s", err.Error())
	}
	if _, err := io.Copy(iniSource, bytes.NewBufferString(iniFileContent)); err != nil {
		return 5212, fmt.Errorf("failed to write ini file: %s", err.Error())
	}
	yamlSource, err := client.SftpClient.Create(ansible_dir + "/" + yamlFilename)
	if err != nil {
		return 5211, fmt.Errorf("failed to open remote file: %s", err.Error())
	}
	if _, err := io.Copy(yamlSource, bytes.NewBufferString(yamlFileContent)); err != nil {
		return 5212, fmt.Errorf("failed to write ini file: %s", err.Error())
	}
	return 2000, nil
}

func getTgtStatus(statusSrc string) (string, string, string) {
	var (
		activeState = ""
		subState    = ""
		errorMsg    = ""
	)
	activeStateRegex := regexp.MustCompile("ActiveState=(.*?)\\n")
	activeStateArr := activeStateRegex.FindStringSubmatch(statusSrc)
	if len(activeStateArr) > 0 {
		activeState = activeStateArr[len(activeStateArr)-1]
	}

	subStateRegex := regexp.MustCompile("SubState=(.*?)\\n")
	subStateArr := subStateRegex.FindStringSubmatch(statusSrc)
	if len(subStateArr) > 0 {
		subState = subStateArr[len(subStateArr)-1]
	}

	errorRegex := regexp.MustCompile("LoadError=(.*?)\\n")
	errorArr := errorRegex.FindStringSubmatch(statusSrc)
	if len(errorArr) > 0 {
		errorMsg = errorArr[len(errorArr)-1]
	}

	return activeState, subState, errorMsg
}

func getAnsibleResult(rawStr string) (AnsibleResult, error) {
	var (
		okStr          = "-1"
		changedStr     = "-1"
		unreachableStr = "-1"
		failedStr      = "-1"
	)

	okRegex := regexp.MustCompile("ok=(.*?) ")
	okArr := okRegex.FindStringSubmatch(rawStr)
	if len(okArr) > 0 {
		okStr = okArr[len(okArr)-1]
	}
	okInt, err := strconv.Atoi(okStr)
	if err != nil {
		return AnsibleResult{}, err
	}

	changedRegex := regexp.MustCompile("changed=(.*?) ")
	changedArr := changedRegex.FindStringSubmatch(rawStr)
	if len(changedArr) > 0 {
		changedStr = changedArr[len(changedArr)-1]
	}
	changedInt, err := strconv.Atoi(changedStr)
	if err != nil {
		return AnsibleResult{}, err
	}

	unreachableRegex := regexp.MustCompile("unreachable=(.*?) ")
	unreachableArr := unreachableRegex.FindStringSubmatch(rawStr)
	if len(unreachableArr) > 0 {
		unreachableStr = unreachableArr[len(unreachableArr)-1]
	}
	unreachableInt, err := strconv.Atoi(unreachableStr)
	if err != nil {
		return AnsibleResult{}, err
	}

	failedRegex := regexp.MustCompile("failed=(.*?) ")
	failedArr := failedRegex.FindStringSubmatch(rawStr)
	if len(failedArr) > 0 {
		failedStr = failedArr[len(failedArr)-1]
	}
	failedInt, err := strconv.Atoi(failedStr)
	if err != nil {
		return AnsibleResult{}, err
	}

	return AnsibleResult{
		Ok:          okInt,
		Changed:     changedInt,
		Unreachable: unreachableInt,
		Failed:      failedInt,
	}, nil

}
